var async = require('async')
var userLoginLogger = require("pomelo-logger").getLogger("userLogin-log");
var httpConf = require("../../../http/httpModule.js")
var util = require("../../../util/util.js")
var robotCfg = require("../../../conf/robot.json")
var url = require("url")
module.exports = function(app) {
  return new Handler(app)
}

var Handler = function(app) {
  this.app = app
  Handler.app = app
  this.sessionService = this.app.get('sessionService')
  this.channelService = this.app.get('channelService')
  this.gameChanel = this.channelService.getChannel("GameChannel",true)
}

var handler = Handler.prototype
var local = {}
var version = "1.0.00&LSKAHDUYAPSMHAKSSA"
var jsonUrl = "https://pdkcnd.5d8d.com/JSON_CFG_2/"
//获取公告
handler.getNotify = function(msg,session,next) {
  var self = this
  self.app.rpc.db.remote.getNotify(session,function(data) {
      next(null,data)
  })
}
//获取微信ticket
handler.getTicket = function(msg,session,next) {
  httpConf.getTicket(next)
}

//游客登录
handler.visitorEnter = function(msg, session, next) {
  var self = this
  var userId = msg.uid //微信ID
  var playerId = userId  //玩家ID
  var channel_appid = msg.channel_appid
  var result = {}
  var loginToken = false
  async.waterfall([
      function(cb) {
        if(userId != undefined){
          cb()
        }else{
          self.app.rpc.db.remote.getPlayerId(session,function(uid) {
              //console.log("uid : "+uid)
              playerId = parseInt(uid) + 1
              userId = parseInt(uid) + 1
              cb()
          })
        }
      },
      function(cb){
        result.openId = playerId
        result.sex = 1
        result.head = ""
        result.nickname = "游客"+playerId
        result.headimgurl = 0
        result.uid = playerId
        result.unionid = playerId
        result.openid = playerId
        result.channel_appid = channel_appid
        //console.log(result)
        result.ip = self.sessionService.getClientAddressBySessionId(session.id).ip
        self.app.rpc.db.remote.check(session,result,msg,function(flag){
            if(flag){
              cb()
            }else{
              next(null,{"flag" : false,msg : "checkError"})
            }
        })
      },
      function(cb) {
        //生成随机登录token
        loginToken = util.randomString()
        self.app.rpc.db.remote.setLoginToken(null,result.unionid,loginToken,null)
        cb(null)
      },
      function() {
        local.login(self,session,userId,playerId,msg.platform,next,msg,function() {
            next(null,{"flag" : true,unionid : result.unionid,loginToken : loginToken})
        })
      }
      ],
    function(err,result) {
      console.log("enter error")
      console.log(err)
      console.log(result)
      next(null,{"flag" : false,code : -200})
      return
    }
  )
}
//H5登录
handler.h5Enter = function(msg,session,next) {
  if(!msg.code || typeof(msg.code) !== "string"){
    next(false)
    return
  }
  var self = this
  httpConf.H5GetData(msg.code,0,function(data) {
    if(data.errcode){
      console.log(data.errmsg)
      next(null,{"flag" : false , code : "tokenError" , "err" : data.errmsg})
      return
    }
    msg.openId = data.openid
    msg.token = data.access_token
    var enterFun = handler.enter.bind(self)
    enterFun(msg,session,next)
  })
}
//微信小游戏使用临时登录凭证code 获取 session_key 和 openid
handler.code2accessToken = function(msg, session, next) {
  var code = msg.code
  if(!code || typeof(code) !== "string"){
    next(null,{flag : false,code: "code error"+code})
    return
  }
  httpConf.code2accessToken(code,0,function(data) {
    next(null,{"flag" : true ,data : data})
  })
}
//微信小游戏使用临时登录凭证code 带appid 获取 session_key 和 openid
handler.code2accessTokenWithAppid = function(msg, session, next) {
  var code = msg.code
  var appid = msg.appid
  if(!code || typeof(code) !== "string" || !appid || typeof(appid) !== "string"){
    next(null,{flag : false,code: "code error || appid error"+code+":"+appid})
    return
  }
  httpConf.code2accessTokenWithAppid(code,appid,0,function(data) {
    next(null,{"flag" : true ,data : data})
  })
}
//微信app登录使用临时登录凭证code 带appid 获取 openid
handler.access_token = function(msg, session, next) {
  var code = msg.code
  var appid = msg.appid
  if(!code || typeof(code) !== "string" || !appid || typeof(appid) !== "string"){
    next(null,{flag : false,code: "code error || appid error"+code+":"+appid})
    return
  }
  httpConf.access_token(code,appid,0,function(data) {
    next(null,{"flag" : true ,data : data})
  })
}
//小游戏登陆
handler.wxgameEnter = function(msg, session, next) {
    var openid = msg.openid
    var session_key = msg.session_key
    var userInfo = msg.userInfo
    var encryptedData = msg.encryptedData
    var iv = msg.iv
    var channel_appid = msg.channel_appid
    var self = this
    console.log("userInfo : ")
    console.log(userInfo)
    var loginToken = false
    if(!msg.version || msg.version !== version){
      next(null,{flag : false,code : "version error : "+msg.version})
      return
    }
    if(!userInfo){
      next(null,{flag : false,code : "userInfo error : "})
      return
    }
    var unionid = httpConf.wxLogin(openid,session_key,encryptedData,iv)
    console.log("openid",openid,"unionid",unionid)
    if(!unionid){
      next(null,{flag : false,code: "session_key error"})
      return
    }
    async.waterfall([
        function(cb){
          userInfo.nickname = strReplace(userInfo.nickname)
          var info = {
            nickname : userInfo.nickName,
            headimgurl : userInfo.avatarUrl,
            sex : userInfo.gender,
            unionid : unionid,
            openid : openid,
            channel_appid : channel_appid
          }
          info.ip = self.sessionService.getClientAddressBySessionId(session.id).ip
          self.app.rpc.db.remote.check(session,info,msg,function(flag){
              if(flag){
                cb()
              }else{
                next(null,{"flag" : false,msg : "checkError"})
              }
          })
        },
        function(cb) {
          //生成随机登录token
          loginToken = util.randomString()
          self.app.rpc.db.remote.setLoginToken(null,unionid,loginToken,null)
          cb(null)
        },
        function() {
          local.login(self,session,unionid,openid,"wxgame",next,msg,function() {
              console.log("login !!")
              next(null,{"flag" : true,unionid : unionid,loginToken : loginToken})
          })
        }
        ],
      function(err,result) {
        console.log("enter error")
        console.log(err)
        console.log(result)
        next(null,{"flag" : false,code : -200})
        return
      }
    )
}
//微信登录
handler.enter = function(msg, session, next) {
  var self = this
  var openId = msg.openId
  var token = msg.token
  var loginToken = false
  var result = {}
  if(!openId || !token){
    next(null,{flag : false,code: "openId || token error : "+openId+"  :  "+token})
    return
  }
  if(!msg.version || msg.version !== version){
    next(null,{flag : false,code : "version error : "+msg.version})
    return
  }
  //登陆验证
  var userId = 0    //微信ID
  var playerId = 0  //玩家ID
  async.waterfall([
      function(cb) {
        httpConf.wxClientLogin(openId,token,function(data) {
            result = data
            if(result == false){
                next(null,{"flag" : false,code : "tokenError"})
            }else{
              cb(null,result)
            }
        })
      },
      function(result,cb){
        // console.log(result)
        userId = result.unionid
        if(!userId){
          next(null,{"flag" : false , "code" : -300})
          return
        }
        result.nickname = strReplace(result.nickname)
        result.ip = self.sessionService.getClientAddressBySessionId(session.id).ip
        self.app.rpc.db.remote.check(session,result,msg,function(flag){
            if(flag){
              cb()
            }else{
              next(null,{"flag" : false,msg : "checkError"})
            }
        })
      },
      function(cb) {
        //生成随机登录token
        loginToken = util.randomString()
        self.app.rpc.db.remote.setLoginToken(null,result.unionid,loginToken,null)
        cb(null)
      },
      function() {
        local.login(self,session,userId,openId,msg.platform,next,msg,function() {
            console.log("login !!")
            console.log({"flag" : true,unionid : result.unionid,loginToken : loginToken})
            next(null,{"flag" : true,unionid : result.unionid,loginToken : loginToken})
        })
      }
      ],
    function(err,result) {
      console.log("enter error")
      console.log(err)
      console.log(result)
      next(null,{"flag" : false,code : -200})
      return
    }
  )
}
//手机账号密码登录
handler.phoneLogin = function(msg, session, next) {
  var phone = msg.phone
  var password = msg.password
  if(!phone || !password){
    next(null,{flag : false,err : "账号或密码为空"})
    return
  }
  var self = this
  self.app.rpc.db.remote.checkLoginPhone(null,phone,password,function(flag) {
    if(flag){
        local.login(self,session,phone,phone,msg.platform,next,msg,function() {
          next(null,{"flag" : true})
        })
    }else{
      next(null,{"flag" : false,code : "phoneLoginError"})
    }
  })
}
//使用token登陆
handler.tokenLogin = function(msg, session, next) {
  var unionid = msg.unionid
  var token = msg.token
  if(!unionid || !token){
    next(null,{flag : false,code: -100})
    return
  }
  // if(!msg.version || msg.version !== version){
  //   next(null,{flag : false,code : -120})
  //   return
  // }
  var self = this
  self.app.rpc.db.remote.checkLoginToken(null,unionid,token,function(flag) {
    if(flag){
        local.login(self,session,unionid,token,msg.platform,next,msg,function() {
          next(null,{"flag" : true})
        })
    }else{
      next(null,{"flag" : false,code : "tokenError"})
    }
  })
}
//统一登陆逻辑
local.login = function(self,session,unionid,openId,platform,next,msg,loginCB) {
      var sessionService = self.app.get('sessionService')
      var uid = undefined
      var notify = {}
      async.waterfall([
          function(cb) {
            // console.log("unionid",unionid)
            self.app.rpc.db.remote.getPlayerInfo(session,unionid,function(data) {
              if(!data){
                console.log("login error : ")
                console.log(data)
                cb(false)
                return
              }
              notify.cmd = "userInfo"
              notify.time = (new Date()).getTime()
              notify.data = data
              notify.data.nickname = strReplace(notify.data.nickname)
              notify.openId = openId
              notify.unionid = unionid
              notify.allGames = data.history ? data.history.allGames : 0
              if(sessionService.getClientAddressBySessionId(session.id)){
                notify.ip = sessionService.getClientAddressBySessionId(session.id).ip
              }
              notify.useDiamond = data.useDiamond
              notify.gold = data.gold
              notify.platform  = platform
              notify.checkSwitch = false
              if(data.freeze == 1){
                next(null,{"flag" : false ,"code" : 500})
                return
              }
              //保存session
              uid = data.uid
              //踢出之前用户
              if( !! sessionService.getByUid(uid)) {
                sessionService.kickBySessionId(sessionService.getByUid(uid)[0].id,function() {
                  cb()
                })
              }else{
                cb()
              }
            })
          },
          function(cb) {
              session.bind(uid)
              session.set("uid", uid)
              session.push("uid", function(err) {
                if(err) {
                  console.error('set uid for session service failed! error is : %j', err.stack)
                  next(null,{"flag" : false ,"code" : "session close"})
                  return
                }
              })
              session.set("nickname",notify.data.nickname)
              session.push("nickname", function(err) {
                if(err) {
                  console.error('set nickname for session service failed! error is : %j', err.stack)
                }
              })
              //connect服务器ID
              session.set("cid", self.app.get('serverId'))
              session.push("cid", function(err) {
                if(err) {
                  console.error('set cid for session service failed! error is : %j', err.stack)
                }
              })
              // console.log("uid : "+session.get("uid"))
              // console.log("nickname : "+session.get("nickname"))
              session.on('closed', onUserLeave.bind(null,self))
              cb(null)
          },
          function(cb){
            self.app.rpc.game.remote.reconnection(session,uid,self.app.get('serverId'),function(data) {
                console.log(data,data.lockinfo)
                notify.reconnection = data.state
                notify.lockinfo = data.lockinfo
                cb(null)
            })
          },
          function() {
            if(!self.gameChanel.getMember(uid)){
              self.gameChanel.add(uid,self.app.get('serverId'))
            }
            notify.jsonUrl = jsonUrl
            console.log("userInfo")
            //通知gameServer
            self.app.rpc.game.remote.userConnect(session,uid,self.app.get('serverId'),function() {
              self.channelService.pushMessageByUids('onMessage', notify, [{
                uid: uid,
                sid: self.app.get('serverId')
              }])
              var info = "    uid : "+uid+"    name ： "+session.get("nickname")
              userLoginLogger.info(info)
            })
            if(loginCB){
              loginCB()
            }
          }
        ],function(err) {
        console.log(err)
    })
}
//接受客户端发送数据
handler.sendData = function(msg, session, next){
    // console.log("code : "+msg.code)
    var self = this
    //判断登录
    var uid = session.get("uid")
    //console.log("uid : "+uid)  
    if(!!uid){
        if(!msg.params){
          msg.params = {}
        }
        msg.params.ip = this.sessionService.getClientAddressBySessionId(session.id).ip
        self.app.rpc.game.remote.receive(session, uid, self.app.get('serverId'), msg.code,msg.params, function(flag,msg){
            next(null,{flag : flag,msg : msg})
        })
    }else{
        next(null,{flag : false,code : 119})
    }
}
//用户离开事件处理
var onUserLeave = function(self, session) {
  if(!session || !session.uid) {
    return
  }
  self.gameChanel.leave(session.uid,self.app.get('serverId'))
  self.app.rpc.game.remote.kick(session,session.uid,self.app.get('serverId'),null)
}

//非法字符串识别
var strReplace = function(str) {
  if(!str){
    return ""
  }
  var strArr = str.split(""),
      result = "",
      totalLen = 0;

  for(var idx = 0; idx < strArr.length; idx ++) {
      // 超出长度,退出程序
      if(totalLen >= 16) break;
      var val = strArr[idx];
      // 英文,增加长度1
      if(/[a-zA-Z]/.test(val)) {
          totalLen = 1 + (+totalLen);
          result += val;
      }
      // 中文,增加长度2
      else if(/[\u4e00-\u9fa5]/.test(val)) {
          totalLen = 2 + (+totalLen);
          result += val;
      }
      // 遇到代理字符,将其转换为 "口", 不增加长度
      else if(/[\ud800-\udfff]/.test(val)) {
          // 代理对长度为2,
          if(/[\ud800-\udfff]/.test(strArr[idx + 1])) {
              // 跳过下一个
              idx ++;
          }
          // 将代理对替换为 "口"
          result += "口";
      }else{
        result += val
      }
  }
  return result
}